import socket
import matplotlib.pyplot as plt
import numpy as np
from collections import deque
from pylab import mpl
import time
import paho.mqtt.publish as publish

# MQTT配置（添加了用户名和密码）
MQTT_BROKER = "127.0.0.1"
MQTT_PORT = 1883
MQTT_TOPIC = "tcp/data/forward"
MQTT_USERNAME = "admin"  # EMQ X用户名
MQTT_PASSWORD = "chdcxy5308996"  # EMQ X密码

# 数据库配置（保留原配置）
DB_CONFIG = {
    'host': '127.0.0.1',
    'user': 'root',
    'password': 'hsp',
    'database': 'tcp_data_db',
    'port': 3306
}

# 服务端监听地址和端口
HOST = '127.0.0.1'
PORT = 8888

# 设置中文显示
mpl.rcParams["font.sans-serif"] = ["SimHei"]
mpl.rcParams["axes.unicode_minus"] = False
np.set_printoptions(formatter={'float': '{: .1f}'.format})

# 初始化数据队列
data_queue = deque(maxlen=20)

# 创建TCP服务端套接字
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind((HOST, PORT))
server_socket.listen(5)
print("等待客户端连接...")

# 接受客户端连接
client_socket, addr = server_socket.accept()
print(f"客户端已连接: {addr}")
client_info = f"{addr[0]}:{addr[1]}"

# 初始化绘图
plt.ion()#开启交互模式
fig, ax = plt.subplots()#创建 Figure（画布） 和 Axes（子图坐标轴）
line, = ax.plot([], [], 'b-')#ax.plot(...) 返回的是包含 1 个 Line2D 对象的列表，加逗号 line,：把列表里的单个元素直接解包给 line，让 line 直接拿到 Line2D 对象（后续可用来更新数据，比如 line.set_data(...) ），不加逗号：line 会变成列表（[Line2D(...)] ），后续操作要写 line[0] 才麻烦。
ax.set_ylim(0, 100)
ax.set_xlim(0, 20)
ax.set_title("实时数据曲线")
ax.set_xlabel("数据点")
ax.set_ylabel("数值")

try:
    while True:
        # 接收TCP数据
        data = client_socket.recv(1024).decode().strip()
        if data:
            num = int(data)
            data_queue.append(num)

            # 更新绘图
            x = np.arange(len(data_queue))
            line.set_data(x, data_queue)
            if len(data_queue) < 20:
                ax.set_xlim(0, 20)
            else:
                ax.set_xlim(0, len(data_queue))
            fig.canvas.draw()
            fig.canvas.flush_events()

            timestamp = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())
            print(f"收到数据: {num}，当前队列: {list(data_queue)}")

            # 通过MQTT发布数据（添加认证信息）
            try:
                auth = {'username': MQTT_USERNAME, 'password': MQTT_PASSWORD}
                publish.single(
                    MQTT_TOPIC,
                    payload=f"{timestamp},{num}",
                    qos=0,
                    hostname=MQTT_BROKER,
                    port=MQTT_PORT,
                    auth=auth
                )
                print(f"已通过MQTT发布数据到主题 {MQTT_TOPIC}")
            except Exception as mqtt_err:
                print(f"MQTT发布失败: {mqtt_err}")

except KeyboardInterrupt:
    print("服务端停止")
finally:
    client_socket.close()
    server_socket.close()
    plt.ioff()
    plt.show()